﻿using System;
using System.Linq;
using CommonCodeManagers.Model;
using log4net;
using log4net.Repository.Hierarchy;
using LibGit2Sharp;
using LibGit2Sharp.Handlers;
using Newtonsoft.Json;

namespace CommonCodeManagers.plugin
{
    public static class GitHandler
    {
        private static string _remoteName = "origin";
        private static string _branchName = "master";

        /// <summary>
        /// 从git 仓库克隆内容
        /// </summary>
        /// <param name="jsonStr"></param>
        /// <param name="localPath"></param>
        public static void CloneRepository(string jsonStr, string localPath)
        {
            string repoPath = Repository.Init(localPath, false);
            if (string.IsNullOrEmpty(jsonStr))
            {
                return;
            }
            var gitAccount = JsonConvert.DeserializeObject<GitAccount>(jsonStr);
            
            try
            {
                var signature = gitAccount.GetSignature();
                using (var repo = new Repository(repoPath))
                {
                    // Set up remote
                    repo.Network.Remotes.Add(_remoteName, gitAccount.Reposity);
                                    
                    // Set up tracking information
                    repo.Branches.Update(repo.Head,
                        b => b.Remote = _remoteName,
                        b => b.UpstreamBranch = "refs/heads/master");
                                        

                    bool wasCalled = false;

                    MergeOptions mergeOptions = new MergeOptions()
                    {
                        OnCheckoutProgress = (path, completed, total) => wasCalled = true,
                        FastForwardStrategy = FastForwardStrategy.FastForwardOnly,
                        MergeFileFavor = MergeFileFavor.Theirs,
                        CheckoutNotifyFlags = CheckoutNotifyFlags.Updated,
                    };


                    PullOptions options = new PullOptions
                    {
                        MergeOptions = mergeOptions,
                        FetchOptions = new FetchOptions
                        {
                            TagFetchMode = TagFetchMode.All,
                            CredentialsProvider = new CredentialsHandler((url, usernameFromUrl, types) =>
                                new UsernamePasswordCredentials()
                                {
                                    Username = gitAccount.UserName,
                                    Password = gitAccount.Password
                                })
                        }
                    };

                    // Pull!
                    MergeResult mergeResult = Commands.Pull(repo, signature, options);

                }
                
                LogHelper.WriteLog("同步成功！");
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("同步失败", ex);
            }            
        }

        /// <summary>
        /// 从Git仓库获取内容
        /// </summary>
        /// <param name="jsonStr">Git账户加密字符串</param>
        /// <param name="key">加密key</param>
        /// <param name="localPath">仓储本地文件夹</param>
        public static void PullText(string jsonStr, string localPath, string key="")
        {
            if (string.IsNullOrEmpty(jsonStr))
            {
                return;
            }
            
            try
            {
                var gitAccount = JsonConvert.DeserializeObject<GitAccount>(jsonStr);

                var signature = gitAccount.GetSignature();

                using (var repo = new Repository(localPath))
                {
                    Branch originMaster = repo.Branches.FirstOrDefault();
                    if (originMaster!=null)
                    {
                        repo.Reset(ResetMode.Hard, originMaster.Tip);
                    }

                    PullOptions options = new PullOptions
                    {
                        MergeOptions = new MergeOptions()
                        {
                            FastForwardStrategy = FastForwardStrategy.FastForwardOnly,
                            MergeFileFavor = MergeFileFavor.Theirs
                        },
                        FetchOptions = new FetchOptions
                        {
                            TagFetchMode = TagFetchMode.All,
                            CredentialsProvider = new CredentialsHandler((url, usernameFromUrl, types) =>
                                new UsernamePasswordCredentials()
                                {
                                    Username = gitAccount.UserName,
                                    Password = gitAccount.Password
                                })
                        }
                    };
                    var rr = Commands.Pull(repo, signature, options);
                }
                LogHelper.WriteLog("同步成功！");
            }
            catch (Exception e)
            {
                LogHelper.WriteLog("同步失败", e);
            }

            
        }

        /// <summary>
        /// 本地文件的内容推送到Git仓库
        /// </summary>
        /// <param name="jsonStr"></param>
        /// <param name="localPath"></param>
        /// <param name="key"></param>
        public static void PushText(string jsonStr, string localPath, string key = "")
        {
            if (string.IsNullOrEmpty(jsonStr))
            {
                return;
            }

            
            try
            {
                var gitAccount = JsonConvert.DeserializeObject<GitAccount>(jsonStr);

                var signature = gitAccount.GetSignature();

                using (var repo = new Repository(localPath))
                {
                    // Stage the file
                    Commands.Stage(repo, "*");
                    // Create the committer's signature and commit
                    var author = signature;
                    var committer = author;
                    // Commit to the repository
                    var commit = repo.Commit("同步时间为：" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), author, committer);
                    // git push
                    var options = new PushOptions
                    {
                        CredentialsProvider = new CredentialsHandler((url, usernameFromUrl, types) => new UsernamePasswordCredentials()
                        {
                            Username = gitAccount.UserName,
                            Password = gitAccount.Password
                        })
                    };
                    var branch = repo.Branches.First();
                    repo.Network.Push(branch, options);
                }
                LogHelper.WriteLog("同步成功！" );
            }
            catch (Exception e)
            {
                LogHelper.WriteLog("同步失败",e);
            }
            
        }
    }
}